-- RandomWordsM
-- Create by huanghr
-- 随机发言模块

module("RandomWordsM", package.seeall);

-- 保留上次发言的时间(单位：分钟)
local retentionTime = 30;

-- 随机发言的三种场景
local WORKSHOP_SCENE = 1;        -- 炼金工坊
local SCOUT_INFO_SCENE = 2;      -- 斥候探索
local SLIME_SCENE  = 3;          -- 天赋树

-- 初始场景发言的概率，20代表20%的概率
local sceneRatio = {
     [1] = 40,
     [2] = 40,
     [3] = 40,
}

-- 随机发言的内容表
local WorkshopWords = {};
local ScoutWords = {};
local SlimeWords = {};

-- 随机发言的权重表
local workshopRatio = {};
local scoutRatio = {};
local slimeRatio = {};

-- 说过的话记录表
local slimeHaveSaid = {};
local workshopHaveSaid = {};
local scoutHaveSaid = {};

-- 载入配置表
local _init = false;
local loadCsv = function()
    if _init then return end
    _init = true;

    WorkshopWords = {};

    -- 转换random_words_CSV表
    local wordsTable = get_random_words_CSV();
    for i = 1, #wordsTable do
        if wordsTable[i].scene_type == WORKSHOP_SCENE then
            WorkshopWords[wordsTable[i].id] = wordsTable[i];
        elseif wordsTable[i].scene_type == SCOUT_INFO_SCENE then
            ScoutWords[wordsTable[i].id] = wordsTable[i];
        elseif wordsTable[i].scene_type == SLIME_SCENE then
            SlimeWords[wordsTable[i].id] = wordsTable[i];
        end
    end

    -- 转换random_words_ratio表(发言类型触发的概率)
    local weightTable = get_random_words_ratio_CSV();
    for j = 1, #weightTable do
        if weightTable[j].scene_type == WORKSHOP_SCENE then
            workshopRatio[weightTable[j].id] = weightTable[j];
        elseif weightTable[j].scene_type == SCOUT_INFO_SCENE then
            scoutRatio[weightTable[j].id] = weightTable[j]
        elseif weightTable[j].scene_type == SLIME_SCENE then
            slimeRatio[weightTable[j].id] = weightTable[j]
        end
    end

    wordsTable = {};
    weightTable = {};
end

-- 模块初始化
function init()
    loadCsv();
end

-- 查询某项值
function query(sceneType, id, path)
    local m = nil;
    if sceneType == WORKSHOP_SCENE then
        m = WorkshopWords[id];
    elseif sceneType == SCOUT_INFO_SCENE then
        m = ScoutWords[id];
    elseif sceneType == SLIME_SCENE then
        m = SlimeWords[id];
    end

    if not m or not path then
        return m;
    end

    return m[path];
end

-- 通过类型获得ID表
function getIdsByType(sceneType, wordsType, excludeIds)
    local t = {};
    if sceneType == WORKSHOP_SCENE then
        t = WorkshopWords;
    elseif sceneType == SCOUT_INFO_SCENE then
        t = ScoutWords;
    elseif sceneType == SLIME_SCENE then
        t = SlimeWords;
    end

    local gainIds = excludeIds or {};

    -- 获得发言类型相同的ID
    local ret = {};
    for id, brief in pairs(t) do
        if wordsType == query(sceneType, id, "words_type")  and table.indexOf(gainIds, id) == -1 then
            table.insert(ret, id);
        end
    end

    return ret;
end

-- 获取随机发言的ID
function getRandomId(sceneType, wordsType, marking, excludeIds)

    local wordsIds = getIdsByType(sceneType, wordsType, excludeIds);

    -- 天赋树冈布奥指定发言
    if sceneType == SLIME_SCENE and wordsType == 101 then
        local ret = {};
        for _, id in pairs(wordsIds) do
            if marking == query(sceneType, id, "pet_id") then
                table.insert(ret, id);
            end
        end
        if #ret > 0 then
            local index = math.random(#ret);
            local id    = ret[index];
            return id;
        end

        return nil;

    else
        if #wordsIds < 1 then
            return nil;
        end

        local index = math.random(#wordsIds);
        local id    = wordsIds[index];
        return id;
    end
end

-- 记录下当前发言的ID
function addHaveSaidId(sceneType, wordsId, marking)
    local haveSaidWord = {};
     -- 编辑所说过的话的记录
    local nowTime = TimeM.getCurrentTime();
    if sceneType == WORKSHOP_SCENE then
        for i = 1, #workshopHaveSaid do
            local tTemp = workshopHaveSaid[i];
            -- marking是位置
            if marking == tTemp.marking then
                if nowTime - tTemp.time >= retentionTime*60 then
                    -- 更新记录
                    workshopHaveSaid[i].time    = nowTime;
                    workshopHaveSaid[i].wordsId = wordsId;
                else
                    -- 未超时直接return
                    return;
                end
            end
        end
        local ret = {["wordsId"] = wordsId, ["time"] = nowTime, ["marking"] = marking};
        table.insert(workshopHaveSaid, ret);

    elseif sceneType == SCOUT_INFO_SCENE then
       -- 说话记录只有一条，直接判断
        if #scoutHaveSaid > 0 then
            if nowTime - scoutHaveSaid[1].time >= retentionTime*60 then
                -- 更新当前的记录
                scoutHaveSaid[1].time = nowTime;
                scoutHaveSaid[1].wordsId = wordsId;
            end
        else
            local ret = {["wordsId"] = wordsId, ["time"] = nowTime}
            table.insert(scoutHaveSaid, ret);
        end

    elseif sceneType == SLIME_SCENE then
        -- 直接更新为最新的记录
        for i = 1, #slimeHaveSaid do
            local tTemp = slimeHaveSaid[i];
            -- marking为冈布奥的ID
            if marking == tTemp.marking then
                slimeHaveSaid[i].wordsId = wordsId;
                slimeHaveSaid[i].time = nowTime;
                return;
            end
        end
        local ret = {["wordsId"] = wordsId, ["time"] = nowTime, ["marking"] = marking};
        table.insert(slimeHaveSaid, ret);
    else
        return;
    end
end

-- 获得的上次说的话的Id
function getOldWordsId(sceneType, marking)
    local nowTime = TimeM.getCurrentTime();

    -- 需要记录随机发言的位置
    if sceneType == WORKSHOP_SCENE then
        local ret = {};
        local removeIndexs = {};
        if #workshopHaveSaid > 0 then
            for i = 1, #workshopHaveSaid do
                local temp = workshopHaveSaid[i];
                if nowTime - temp.time < retentionTime*60 then
                    local wordsInfo = {["wordsId"] = temp.wordsId, ["pos"] = temp.marking};
                    table.insert(ret, wordsInfo);
                else
                    -- 记录超时数据的index
                    table.insert(removeIndexs, i);
                end
            end

            -- 移除已超时的数据
            if #removeIndexs > 0 then
                for j = 1, #removeIndexs do
                    table.remove(workshopHaveSaid, removeIndexs[j]);
                end
            end
        end

        if #ret > 0 then
            return ret;
        end

        return nil;

    elseif sceneType == SCOUT_INFO_SCENE then
        -- 斥候探索界面
        local wordsId = nil;
        if #scoutHaveSaid > 0 then
            local removeIndexs = {};
            for i = 1, #scoutHaveSaid do
                local temp = scoutHaveSaid[i];
                if nowTime - temp.time < retentionTime*60 then
                    wordsId = temp.wordsId;
                else
                    table.insert(removeIndexs, i);
                end
            end

            if #removeIndexs > 0 then
                for j = 1, #removeIndexs do
                    table.remove(scoutHaveSaid, removeIndexs[j]);
                end
            end
        end
        return wordsId;

    elseif sceneType == SLIME_SCENE then
        if #slimeHaveSaid > 0 then
            local removeIndexs = {};
            for i = 1, #slimeHaveSaid do
                local temp = slimeHaveSaid[i];
                if marking == temp.marking then
                    if nowTime - temp.time < retentionTime*60 then
                        return temp.wordsId;
                    else
                        -- 删除超时ID
                        table.insert(removeIndexs, i);
                    end
                end
            end

            -- 移除已超时的数据
            if #removeIndexs > 0 then
                for j = 1, #removeIndexs do
                    table.remove(slimeHaveSaid, removeIndexs[j]);
                end
            end
        end

        return nil;

     else
        return nil;
     end
end

-- 获得权重表
function getWordsIdAndWeigt(sceneType)
    local wordsIdAndWeight = {};

    -- 炼金工坊界面
    if sceneType == WORKSHOP_SCENE then
        for _, value in pairs(workshopRatio) do
            --  触发类发言概率为100， 不计入发言
            if value.ratio ~= 100 then
                local ret = {["type"] = value.words_type, ["ratio"] = value.ratio};
                table.insert(wordsIdAndWeight, ret);
            end
       end

    -- 斥候探索界面
    elseif sceneType == SCOUT_INFO_SCENE then
        for _, value in pairs(scoutRatio) do
            local ret = {["type"] = value.words_type, ["ratio"] = value.ratio};
            table.insert(wordsIdAndWeight, ret);
        end

    -- 世界树界面
    elseif sceneType == SLIME_SCENE then
        for _, value in pairs(slimeRatio) do
            local ret = {["type"] = value.words_type, ["ratio"] = value.ratio};
            table.insert(wordsIdAndWeight, ret);
        end
    end

    return wordsIdAndWeight;
end

-- 计算权重对应的范围（默认为100）
function calcRangeByScene(sceneType)
    local ret = getWordsIdAndWeigt(sceneType)
    local weightRange = {};
    local range = 0;
    for i = 1, #ret do
        range = range + ret[i].ratio;
        local t = {["type"] = ret[i].type, ["range"] = range};
        table.insert(weightRange, t);
    end

    -- 从小到大排序
    local function sortRange(element1, element2)
        return element1.range < element2.range;
    end

    table.sort(weightRange, sortRange);
    return weightRange;
end

-- 获得场景发言的概率
function getSceneRatio(sceneType)
    return sceneRatio[sceneType];
end
